﻿//-----------------------------------------------------------------------
// <copyright file="IMergeCellInternal.cs" company="LMT">
//     Copyright (c) by La Minh Thuận.
// </copyright>
// <author>thuanla1985@hotmail.com</author>
//-----------------------------------------------------------------------
namespace LMT.Forms
{
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Windows.Forms.Design;

    /// <summary>
    /// The font drop down toolstrip control
    /// </summary>
    [DesignerCategory("code")]
    [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.All)]
    public sealed partial class ToolStripFontComboBox : ToolStripComboBox
    {
        /// <summary>
        /// stores the width of the largest item
        /// </summary>
        private int dropWidth;

        /// <summary>
        /// detect whether font list is populate on the controls
        /// </summary>
        private bool isPopulate;

        /// <summary>
        /// Initializes a new instance of the <see cref="ToolStripFontComboBox"/> class.
        /// </summary>
        public ToolStripFontComboBox()
        {
            // Set the draw mode so we can take over item drawing
            this.ComboBox.DrawMode = DrawMode.OwnerDrawVariable;
            this.ComboBox.MaxDropDownItems = 20;

            // Handle the events
            this.ComboBox.MeasureItem += new MeasureItemEventHandler(this.ComboBoxMeasureItem);
            this.ComboBox.DrawItem += new DrawItemEventHandler(this.ComboBoxDrawItem);
        }

        /// <summary>
        /// Populates the fonts.
        /// </summary>
        public void PopulateFonts()
        {
            if (!this.isPopulate)
            {
                foreach (FontFamily ff in FontFamily.Families)
                {
                    if (ff.IsStyleAvailable(FontStyle.Regular))
                    {
                        this.Items.Add(ff.GetName(0));
                    }
                }

                if (Items.Count > 0)
                {
                    this.SelectedIndex = 0;
                }

                this.isPopulate = true;
            }
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.ToolStripComboBox.DropDown"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnDropDown(EventArgs e)
        {
            this.ComboBox.DropDownWidth = this.dropWidth == 0 ? this.Size.Width : this.dropWidth;
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.ToolStripComboBox.OnPaint"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data.</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            // because no event or window message for loading control, we must use the paint event for loading font.
            if (!this.DesignMode && !this.isPopulate)
            {
                this.Parent.BeginInvoke(new MethodInvoker(delegate
                {
                    this.PopulateFonts();
                }));
            }

            base.OnPaint(e);
        }

        /// <summary>
        /// Handles the MeasureItem event of the ComboBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MeasureItemEventArgs"/> instance containing the event data.</param>
        private void ComboBoxMeasureItem(object sender, MeasureItemEventArgs e)
        {
            if (e.Index > -1)
            {
                string fontName = this.Items[e.Index].ToString();
                Graphics g = this.ComboBox.CreateGraphics();
                SizeF size = g.MeasureString(fontName, new Font(fontName, 13));

                // Set the Item’s Width, and iDropWidth if the item has a greater width
                e.ItemWidth = (int)size.Width;
                if (e.ItemWidth > this.dropWidth)
                {
                    this.dropWidth = e.ItemWidth;
                }

                // If .NET gives you problems drawing fonts with different heights, set a maximum height
                e.ItemHeight = (int)size.Height;
            }
        }

        /// <summary>
        /// Comboes the box draw item.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.DrawItemEventArgs"/> instance containing the event data.</param>
        /// <remarks>
        /// <list type="note">
        ///     <item>DropDownStyle = DropDown, so we should draw the popup menu only, because the combobox text will be draw by Framework.</item>
        ///     <item>DropDownStyle = DropDownList, so we must handle all drawing the popup menu and combobox text.</item>
        /// </list>
        /// </remarks>
        private void ComboBoxDrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index > -1)
            {
                // disable mode & no focus & selected
                bool disable = e.State == (DrawItemState.Disabled | DrawItemState.ComboBoxEdit | DrawItemState.NoAccelerator | DrawItemState.NoFocusRect);

                string fontName = this.Items[e.Index].ToString();

                // don't draw background if it's in disable mode and no focus & selected
                if (disable | !this.Enabled)
                {
                    e.Graphics.DrawString(fontName, this.Font, SystemBrushes.GrayText, e.Bounds.Location);
                }
                else
                {
                    Font drawFont = new Font(fontName, 13);

                    e.DrawBackground();

                    // This is for drawing combobox text
                    if (e.State == DrawItemState.ComboBoxEdit |
                        e.State == (DrawItemState.ComboBoxEdit | DrawItemState.Selected | DrawItemState.Focus) |
                        e.State == (DrawItemState.ComboBoxEdit | DrawItemState.NoAccelerator | DrawItemState.NoFocusRect) |
                        e.State == (DrawItemState.ComboBoxEdit | DrawItemState.NoAccelerator | DrawItemState.NoFocusRect | DrawItemState.Selected | DrawItemState.Focus))
                    {
                        e.Graphics.DrawString(fontName, this.Font, SystemBrushes.WindowText, e.Bounds.Location);
                    }
                    else
                    {
                        // This is for drawing the dropdown popup menu.
                        if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
                        {
                            e.Graphics.DrawString(fontName, drawFont, SystemBrushes.HighlightText, e.Bounds.Location);
                        }
                        else
                        {
                            e.Graphics.DrawString(fontName, drawFont, SystemBrushes.WindowText, e.Bounds.Location);
                        }
                    }

                    drawFont.Dispose();
                }
            }
        }
    }
}